package com.kexio.core.security;

import com.kexio.core.properties.CoreProperties;
import com.kexio.core.security.filter.SecurityFilter;
import com.kexio.core.security.filter.UserContextInitFilter;
import com.kexio.core.security.jwt.JwtService;
import com.kexio.core.security.jwt.JwtTokenProvider;
import com.kexio.core.security.jwt.JwtTokenValidator;
import com.kexio.core.security.service.AuthenticationService;
import com.kexio.core.security.service.RbacService;
import com.kexio.core.security.service.UserContextService;
import com.kexio.core.security.service.impl.DefaultAuthenticationService;
import com.kexio.core.security.service.impl.DefaultRbacService;
import com.kexio.core.security.service.impl.DefaultUserContextService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;

/**
 * Security安全模块自动配置类
 *
 * @author Kexio Team
 * @since 1.0.0
 */
@AutoConfiguration
@EnableConfigurationProperties(CoreProperties.class)
@ConditionalOnProperty(prefix = "kexio.core.security", name = "enabled", havingValue = "true", matchIfMissing = true)
public class SecurityAutoConfiguration {

    private static final Logger log = LoggerFactory.getLogger(SecurityAutoConfiguration.class);

    public SecurityAutoConfiguration() {
        log.info("==> Kexio Security 自动配置已启用");
    }

    /**
     * JWT服务
     */
    @Bean
    @ConditionalOnMissingBean
    public JwtService jwtService(CoreProperties coreProperties) {
        return new JwtService(coreProperties);
    }

    /**
     * JWT令牌提供者
     */
    @Bean
    @ConditionalOnMissingBean
    public JwtTokenProvider jwtTokenProvider(JwtService jwtService) {
        return new JwtTokenProvider(jwtService);
    }

    /**
     * JWT令牌验证器
     */
    @Bean
    @ConditionalOnMissingBean
    public JwtTokenValidator jwtTokenValidator(JwtService jwtService) {
        return new JwtTokenValidator(jwtService);
    }

    /**
     * 用户上下文服务
     */
    @Bean
    @ConditionalOnMissingBean
    public UserContextService userContextService() {
        return new DefaultUserContextService();
    }

    /**
     * 认证服务
     */
    @Bean
    @ConditionalOnMissingBean
    public AuthenticationService authenticationService(JwtTokenProvider jwtTokenProvider,
                                                       JwtTokenValidator jwtTokenValidator,
                                                       UserContextService userContextService) {
        return new DefaultAuthenticationService(jwtTokenProvider, jwtTokenValidator, userContextService);
    }

    /**
     * RBAC权限控制服务
     */
    @Bean
    @ConditionalOnMissingBean
    public RbacService rbacService() {
        return new DefaultRbacService();
    }

    /**
     * 安全过滤器
     */
    @Bean
    public SecurityFilter securityFilter(JwtTokenValidator jwtTokenValidator,
                                         UserContextService userContextService) {
        return new SecurityFilter(jwtTokenValidator, userContextService);
    }

    /**
     * 用户上下文初始化过滤器
     */
    @Bean
    public UserContextInitFilter userContextInitFilter(UserContextService userContextService) {
        return new UserContextInitFilter(userContextService);
    }

    /**
     * 注册安全过滤器
     */
    @Bean
    public FilterRegistrationBean<SecurityFilter> securityFilterRegistration(SecurityFilter securityFilter) {
        FilterRegistrationBean<SecurityFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(securityFilter);
        registration.addUrlPatterns("/api/*");
        registration.setName("securityFilter");
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
        return registration;
    }

    /**
     * 注册用户上下文初始化过滤器
     */
    @Bean
    public FilterRegistrationBean<UserContextInitFilter> userContextInitFilterRegistration(
            UserContextInitFilter userContextInitFilter) {
        FilterRegistrationBean<UserContextInitFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(userContextInitFilter);
        registration.addUrlPatterns("/*");
        registration.setName("userContextInitFilter");
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return registration;
    }
}
